#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <functional>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#include "Task.hpp"
#include "Channel.hpp"

using work_t = std::function<void()>;

enum
{
    OK = 0,
    UsageError,
    PipeError,
    ForkError
};

class ProcessPool
{
public:
    ProcessPool(int processnum, work_t work)
        : _processnum(processnum), _work(work)
    {}

    ~ProcessPool()
    {}

    int InitProcessPool()
    {
        for (int i = 0; i < _processnum; i++)
        {
            // 1.创建管道
            int pipefd[2] = {0};
            int n = pipe(pipefd);
            if (n < 0)
                return PipeError;

            // 2.创建子进程
            pid_t id = fork();
            if (id < 0)
                return ForkError;

            // 3.建立通信信道
            if (id == 0)
            {
                // version 3
                // 关闭历史的wfd 
                std::cout << "child: " << getpid() << ", close history fd: ";
                for(auto& c : _channels)
                {
                    std::cout << c.Wfd() << " ";
                    c.Close();
                }
                std::cout << "over" << std::endl;

                // 子进程: read
                ::close(pipefd[1]);

                std::cout << "child pid: " << getpid() << ", read: " << pipefd[0] << std::endl;
                ::dup2(pipefd[0], 0);
                _work();
                ::exit(0);
            }

            // 父进程: write
            ::close(pipefd[0]);
            _channels.emplace_back(pipefd[1], id);
        }
        return OK;
    }

    void Debug()
    {
        for (auto &c : _channels)
        {
            std::cout << c.Name() << std::endl;
        }
    }

    void DispatchTask()
    {
        int who = 0;
        int num = 10;
        while (num--)
        {
            // 1.选择一个任务
            int task = tm.SelectTask();

            // 2.选择一个管道
            Channel &curr = _channels[who++];
            who %= _channels.size();

            std::cout << "########################################################" << std::endl;
            std::cout << "send " << task << " to " << curr.Name() << ", 任务还剩: " << num << std::endl;
            std::cout << "########################################################" << std::endl;

            // 3.通过管道派发任务给子进程
            curr.Send(task);

            sleep(1);
        }
        std::cout << std::endl;
    }

    void CleanProcessPool()
    {
        // version 1
        // // 1.关闭所有的写端
        // for (auto &c : _channels)
        // {
        //     c.Close();
        // }
        // // 2.等待子进程退出
        // for (auto &c : _channels)
        // {
        //     pid_t rid = ::waitpid(c.Id(), nullptr, 0);
        //     if (rid > 0)
        //     {
        //         std::cout << "child pid: " << rid << " wait success" << std::endl;
        //     }
        // }

        // version 2
        // for (int i = _channels.size() - 1; i >= 0; i--)
        // {
        //     // 倒着关闭所有管道的写端
        //     _channels[i].Close();
        //     pid_t rid = ::waitpid(_channels[i].Id(), nullptr, 0);
        //     if (rid > 0)
        //     {
        //         std::cout << "child pid: " << rid << " wait success" << std::endl;
        //     }
        // }

        // version 3
        for (auto &c : _channels)
        {
            c.Close();
            pid_t rid = ::waitpid(c.Id(), nullptr, 0);
            if (rid > 0)
            {
                std::cout << "child pid: " << rid << " wait success" << std::endl;
            }
        }
    }

private:
    std::vector<Channel> _channels;
    int _processnum;
    work_t _work; // 回调函数
};